In [24]:
    
%run ../trajectory.ipynb
import csv
    
    
    
This document is for comparing different configurations of liquid propellant. Before a design optimization can occur, we must specify certain propellant characteristics, as determined by our selection and the outputs of CEArun. However, it is not immediately obvious from just thermodynamic properties how various propellant configurations will effect the rocket's performance as a whole. Hence, this.
In order to compare propellant configurations, we make the ceterus paribus assumption that all other aspects of the LV4 rocket are held constant. The canonical outputs of our Multi-disciplinary Design Optimization are used to dictate the total mass of propellants, total mass flow rates, and exit pressure. The same trajectory simulation that is used in the MDO is used here to numerically integrate the results of launching a rocket with a given propellant configuration.
We must explicitly choose the following pieces of information:
The following pieces of information are given by CEArun:
This script requires only a .csv file with one row for each propellant configuration and one column for each parameter.
The relevant outputs of each trajectory simulation are saved as a text file.
In [2]:
    
# canonical lv4 design variables
m_prop_can = 123.35069377654865
mdot_can   = 2.6244828455178943
p_e_can    = 42.974369360377864
# canonical propellant configuration, for reference
# combustion gas properties ke, Re, T_ch, determined from CEArun
# with chamber pressure=350 psi, fuel temp=419.15 K, 
#      lox temp=90 K, OF=1.3 for fuel = 64.8% IPA (2propanol) / 35.2% H20
rho_ipa = 849.28   # kg/m^3  Density of 64.8% IPA / 35.2% H20
OF   = 1.3        # O/F ratio, this is somewhat arbitrary but CEA says its good.
p_ch = 350 # chamber pressure, PSI
T_ch = 3097.82 # chamber temperature, K
ke   = 1.1251 # specific heat ratio, propellant (aka gammas)
M    = 23.196 # molar mass
Re   = spec_gas(M) # specific gas constant, propellant
    
First of all, I'm sorry about the hacky use of global variables. They don't cause any problems, but they are unsightly.
test_run takes a given propellant configuration, runs a trajectory simulation, and returns the simulation object.
print_results takes a simulation object and an index number, and saves all the relevant information from the trajectory to a text file in ./propellants/ named by the index.
load_csv takes a string that names a .csv file, and returns an isomorphic multidimensional array.
run_batch takes no explicit arguments and the name of the .csv file as an implicit parameter, and then runs and saves a trajectory simulation for each propellant configuration.
The last code block of this document simply calls run_batch(). The end-user need only concern themself with setting up the .csv file correctly.
In [3]:
    
def test_run(ipa, OF_param, p_ch, T_ch, ke, M, comment): # OF implicitly invoked, don't worry
    global OF, rho_ipa # I SAID I'M SORRY!!
    rho_ipa = ipa
    OF = OF_param
    Re = spec_gas(M)
    sim = trajectory(m_prop_can, mdot_can, dia, p_e_can,
                     p_ch=p_ch, T_ch=T_ch, ke=ke, Re=Re)
    sim.comment = comment
    sim.OF = OF_param
    sim.ipa = rho_ipa
    sim.M = M
    return sim
    
In [4]:
    
# this creates a list of relevant strings from trajectory
def print_results(sim, index):
    text_base = [] # list of lines of strings
    
    np.set_printoptions(precision=3) # this line may be deprecated, i copy-pasted most of this section
    
    text_base.append('INPUTS')
    text_base.append('\nComment: ' + sim.comment)
    text_base.append('\nFuel density                               = %5.3f kg/m^3' % sim.ipa)
    text_base.append('\nO/F ratio                                  = %5.3f ' % sim.OF)
    text_base.append('\nchamber pressure                           = {:.3f} kPa'.format(sim.p_ch/1000))
    text_base.append('\nChamber temperature                        = {:.3f} K'.format(sim.T_ch))
    text_base.append('\nSpecific heat ratio                        = %5.3f' % sim.ke)
    text_base.append('\nMolar mass                                 = %5.3f' % sim.M)
    text_base.append('\nSpecific gas constant                      = %5.3f J/K' % sim.Re)
    text_base.append('\n')
    text_base.append('\nDESIGN PARAMETERS')
    text_base.append('\n-----------------------------')
    text_base.append('\ndesign total propellant mass               = {:.3f} kg'.format(m_prop_can))
    text_base.append('\ndesign mass flow rate                      = {:.3f} kg/s'.format(mdot_can))
    text_base.append('\ndesign nozzle exit pressure                = {:.3f} kPa'.format(p_e_can))
    text_base.append('\n')
    text_base.append("\nENGINE SYSTEM DETAILS")
    text_base.append("\n-----------------------------")
    text_base.append('\ndesign Throat pressure                     = {:.3f} kPa'.format(sim.p_t/1000))
    text_base.append('\ndesign Throat temperature                  = {:.3f} K'.format(sim.T_t))
    text_base.append('\ndesign exit velocity                       = {:.3f} m/s'.format(sim.Ve))
    text_base.append('\ndesign thrust (ground level)               = {:.3f} kN'.format(sim.F[0]/1000))
    text_base.append('\ndesign thrust (vacuum)                     = {:.2f} kN'.format(sim.F[sim.F_index]/1000))
    text_base.append('\ndesign expansion ratio                     = {:.3f}'.format(sim.ex))
    text_base.append('\ndesign Exit area                           = {:.3f} in.^2'.format(sim.A_e/0.0254**2))
    text_base.append('\ndesign throat area                         = {:.3f} in.^2'.format(sim.A_t/0.0254**2))
    text_base.append('\ndesign isp                                 = {:.3f} s'.format(sim.Ve/g_n))
    text_base.append('\ndesign total impulse                       = {:.3f} kN*s'.format(
                                                  sim.t[sim.F_index]*(sim.F[sim.F_index]/1000 + sim.F[0]/1000)/2))
    text_base.append('\ndesign dV                                  = {:.3f} km/s'.format(sim.dV1))
    text_base.append('\nmission time at burnout                    = {:.3f} s'.format(sim.t[sim.F_index]))
    
    text_base.append('\n\nPlumbing Details\n------------------')
    # Mass flow for each propllent
    mdot_o, mdot_f = proportion(mdot_can)
    text_base.append("\nOx flow: . . . . . . . . . . %7.3f kg/s" % mdot_o)
    text_base.append("\nFuel flow:                   %7.3f kg/s" % mdot_f)
    
    # Propellent Mass for each propllent
    mprop_o, mprop_f = proportion(m_prop_can)
    text_base.append("\nOx mass: . . . . . . . . . . . %5.3f kg" % mprop_o)
    text_base.append("\nFuel mass:                     %5.3f kg" % mprop_f)
    
    # dimensions of each tank
    text_base.append("\nTank outer diameters: . . . . . . . %7.3f m" % (2*sim.r))
    text_base.append("\nOx tank length + ullage:      %7.3f m" % sim.l_o)
    text_base.append("\nFuel tank length + ullage:    %7.3f m" % sim.l_f)
    
    # Tank thickness for each tank (mm)
    thickness_o = tank_thickness(Al, sim.r)
    thickness_f = tank_thickness(CF, sim.r)
    text_base.append("\nOx tank thickness:            %5.3f mm" % (thickness_o*1000))
    text_base.append("\nFuel tank thickness:          %5.3f mm" % (thickness_f*1000))
    
    # Mass of each tank
    m_tank_o = tank_mass(sim.l_o, Al, sim.r)
    m_tank_f = tank_mass(sim.l_f, CF, sim.r)
    
    text_base.append("\nOx tank mass: . . . . . . . . %5.3f kg" % m_tank_o)
    text_base.append("\nFuel tank mass:               %5.3f kg" % m_tank_f)
    
    
    text_base.append('\n')
    text_base.append('\nRELEVANT CONSTRAINTS')
    text_base.append('\n-----------------------------')
    text_base.append('\naltitude at apogee (c.f. > {})          = {:.3f} km'.format(
                                                                                cons_alt/1000, sim.alt[-1]/1000))
    text_base.append("\nmax acceleration (c.f. < {})               = {:.3f} gs".format(
                                                                                cons_accel, sim.max_g_force))
    text_base.append('\nTWR at lift off (c.f. > {})                 = {:.3f}'.format(cons_TWR, sim.TWR))
    text_base.append('\nspeed when leaving launch rail (c.f. > {}) = {:.3f} m/s'.format(cons_ls,sim.launch_speed))
    
    with open('propellants/'+str(index)+'_info.txt', 'w') as info:
        for line in text_base:
            info.write(line)
    
In [5]:
    
def load_csv(file_name):
    designs = []
    with open(file_name) as text:
        csv_reader = csv.reader(text, delimiter=',')
        counter = 0
        for line in csv_reader:
            if counter != 0:
                designs.append(line)
            counter += 1
    return designs
    
In [6]:
    
def run_batch():
    designs = load_csv('propellants/propellants.csv')
    for i, des in enumerate(designs):
        run = test_run(float(des[0]), float(des[1]), float(des[2]),
                       float(des[3]), float(des[4]), float(des[5]), des[6])
        print_results(run, i)
    
In [7]:
    
run_batch()